`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/04/18 10:33:00
// Design Name: 
// Module Name: master
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

//sel=0,master=0,往slave0的0-31地址写入数据0-31
//sel=0,master=1,往slave0的32-63地址写入数据32-63
//sel=1,master=2,往slave1的64-95地址写入数据64-95
//sel=1,master=3,往slave1的96-127地址写入数据96-127

module master
#(parameter N=0,
  parameter TEST_LEN=32)
(
input logic start_w,
input logic start_r,
input logic sel_w,
input logic sel_r,
//
AXI4_Lite.Master m,
output logic done
    );
//32个测试数据
logic [31:0] wr_cnt;
logic [31:0] rd_cnt;
logic [31:0] wr_addr;
logic [31:0] rd_addr;
logic [31:0] rd_data [0:TEST_LEN-1];
logic [31:0] test_data [0:TEST_LEN-1];
initial
begin
   for(int i=0;i<TEST_LEN;i++)
       test_data[i]=N*TEST_LEN+i;                                //主机N测试数据N*32--N*32+31
end
//wstrb
assign m.wstrb=4'b1111;
//awvalid
always@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
    m.awvalid<=0;
else if(start_w)
    m.awvalid<=1;
else if(m.awvalid&&m.awready)
begin
    m.awvalid<=0;
	$display("$time=%p,Mater%d address channel hankshake finished",$time,N);
end
else if(m.bvalid&&m.bready&&wr_cnt<TEST_LEN-1)                    //上一次写结束,但写的次数还未全部完成
begin
    #(($urandom%20)*10)
    m.awvalid<=1;
end
//wvalid
always_ff@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
    m.wvalid<=0;
else if(m.awvalid&&m.awready)
    m.wvalid<=1;
else if(m.wvalid&&m.wready)
begin
    m.wvalid<=0;
	$display("$time=%p,Master%d data channel handshake finished",$time,N);
end
//awaddr
always_ff@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
    m.awaddr<=0;
else if(start_w)
    m.awaddr<=N*TEST_LEN*4;                           //第N个主机写的起始地址为N*32
else if(m.bvalid&&m.bready&&wr_cnt<TEST_LEN-1)
    m.awaddr<=m.awaddr+4;
//wdata
always_comb
    m.wdata=test_data[wr_cnt];
//wr_cnt
always_ff@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
    wr_cnt<=0;
else if(m.bvalid&&m.bready)
    wr_cnt<=wr_cnt+1;
//bready
always_ff@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
    m.bready<=0;
else if(m.awvalid&&m.awready)
    m.bready<=1;
else if(m.bvalid&&m.bready)
begin
    m.bready<=0;
	$display("$time=%p,Master%d response channel handshake finished",$time,N);
end
//done
assign done=(m.bvalid&&m.bready&&wr_cnt==TEST_LEN-1)||(m.rvalid&&m.rready&&rd_cnt==TEST_LEN-1);
//*****************************************************读********************************************
//m.araddr
always@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
   m.araddr<=0;
else if(start_r)
   m.araddr<=N*TEST_LEN*4;
else if(m.rvalid&&m.rready&&rd_cnt<TEST_LEN-1)
   m.araddr<=m.araddr+4;
//m.arvalid
always@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
   m.arvalid<=0;
else if(start_r)
   m.arvalid<=1;
else if(m.arvalid&&m.arready)
   m.arvalid<=0;
else if(m.rvalid&&m.rready&&rd_cnt<TEST_LEN-1)
begin
   #(($urandom%20)*10)
   m.arvalid<=1;
end

//m.rready
always@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
   m.rready<=0;
else if(m.arvalid&&m.arready)
   m.rready<=1;
else if(m.rvalid&&m.rready)
   m.rready<=0;
//rd_cnt
always@(posedge m.aclk,negedge m.aresetn)
if(~m.aresetn)
   rd_cnt<=0;
else if(m.rvalid&&m.rready)
   rd_cnt<=rd_cnt+1;
//read data
always@(posedge m.aclk)
if(m.rvalid&&m.rready)
   rd_data[rd_cnt]<=m.rdata;
//
initial
begin
    wait(m.rvalid&&m.rready&&rd_cnt==TEST_LEN-1);
	repeat(10)
	    @(posedge m.aclk);
    for(int i=0;i<TEST_LEN;i++)
	begin
	    if(test_data[i]!=rd_data[i])
		begin
		    $display("master%d error",N);
			$finish;
		end
	end
	$display("master%d right",N);
			
end
endmodule
